﻿#region Copyright (c) 2000-2013 Developer Express Inc.
/*
{*******************************************************************}
{                                                                   }
{       Developer Express .NET Component Library                    }
{                                                                   }
{                                                                   }
{       Copyright (c) 2000-2013 Developer Express Inc.              }
{       ALL RIGHTS RESERVED                                         }
{                                                                   }
{   The entire contents of this file is protected by U.S. and       }
{   International Copyright Laws. Unauthorized reproduction,        }
{   reverse-engineering, and distribution of all or any portion of  }
{   the code contained in this file is strictly prohibited and may  }
{   result in severe civil and criminal penalties and will be       }
{   prosecuted to the maximum extent possible under the law.        }
{                                                                   }
{   RESTRICTIONS                                                    }
{                                                                   }
{   THIS SOURCE CODE AND ALL RESULTING INTERMEDIATE FILES           }
{   ARE CONFIDENTIAL AND PROPRIETARY TRADE                          }
{   SECRETS OF DEVELOPER EXPRESS INC. THE REGISTERED DEVELOPER IS   }
{   LICENSED TO DISTRIBUTE THE PRODUCT AND ALL ACCOMPANYING .NET    }
{   CONTROLS AS PART OF AN EXECUTABLE PROGRAM ONLY.                 }
{                                                                   }
{   THE SOURCE CODE CONTAINED WITHIN THIS FILE AND ALL RELATED      }
{   FILES OR ANY PORTION OF ITS CONTENTS SHALL AT NO TIME BE        }
{   COPIED, TRANSFERRED, SOLD, DISTRIBUTED, OR OTHERWISE MADE       }
{   AVAILABLE TO OTHER INDIVIDUALS WITHOUT EXPRESS WRITTEN CONSENT  }
{   AND PERMISSION FROM DEVELOPER EXPRESS INC.                      }
{                                                                   }
{   CONSULT THE END USER LICENSE AGREEMENT FOR INFORMATION ON       }
{   ADDITIONAL RESTRICTIONS.                                        }
{                                                                   }
{*******************************************************************}
*/
#endregion Copyright (c) 2000-2013 Developer Express Inc.

using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
using UColor.Core.Helpers;
using UColor.WPF.Helpers;
using DevExpress.Xpf.Core.Native;
using DevExpress.Xpf.Editors;
using System.Linq;
namespace UColor.WPF {
	public class ModuleHelper : DependencyObject {
		#region Dependency Properties
		public static readonly DependencyProperty DescriptionRowsCountProperty;
		public static readonly DependencyProperty LinksProperty;
		public static readonly DependencyProperty OptionsTopTextProperty;
		public static readonly DependencyProperty IsPopupContentInvisibleProperty;
		public static readonly DependencyProperty IsRTLSupportedProperty;
		public static readonly DependencyProperty DemoModuleViewProperty;
		public static readonly DependencyProperty DemoModuleOptionsViewProperty;
		public static readonly DependencyProperty OptionsExpandedProperty;
		public static readonly DependencyProperty DemoModuleProperty;
		public static readonly DependencyProperty DemoFlowDirectionProperty;
		public static readonly DependencyProperty OwnerProperty;
		public static readonly DependencyProperty SidebarVisibilityProperty;
		public static readonly DependencyProperty SidebarTagProperty;
		public static readonly DependencyProperty SidebarIconProperty;
		public static readonly DependencyProperty SidebarIconSelectedProperty;
		static ModuleHelper() {
			Type ownerType = typeof(ModuleHelper);
			DescriptionRowsCountProperty = DependencyProperty.Register("DescriptionRowsCount", typeof(int), ownerType, new PropertyMetadata(1, RaiseDescriptionRowsCountChanged));
			LinksProperty = DependencyProperty.Register("Links", typeof(List<object>), ownerType, new PropertyMetadata(null, RaiseLinksChanged));
			OptionsTopTextProperty = DependencyProperty.Register("OptionsTopText", typeof(string), ownerType, new PropertyMetadata(string.Empty, RaiseOptionsTopTextChanged));
			IsPopupContentInvisibleProperty = DependencyProperty.Register("IsPopupContentInvisible", typeof(bool), ownerType, new PropertyMetadata(true, RaiseIsPopupContentInvisibleChanged));
			IsRTLSupportedProperty = DependencyProperty.Register("IsRTLSupported", typeof(bool), ownerType, new PropertyMetadata(false, RaiseIsRTLSupportedChanged));
			DemoModuleViewProperty = DependencyProperty.Register("DemoModuleView", typeof(DemoModuleControlView), ownerType, new PropertyMetadata(DemoModuleControlView.Demo, RaiseDemoModuleViewChanged));
			DemoModuleOptionsViewProperty = DependencyProperty.Register("DemoModuleOptionsView", typeof(DemoModuleControlOptionsView), ownerType, new PropertyMetadata(DemoModuleControlOptionsView.Options, RaiseDemoModuleOptionsViewChanged));
			OptionsExpandedProperty = DependencyProperty.Register("OptionsExpanded", typeof(bool), ownerType, new PropertyMetadata(true, RaiseOptionsExpandedChanged));
			DemoModuleProperty = DependencyProperty.Register("DemoModule", typeof(FrameworkElement), ownerType, new PropertyMetadata(null, RaiseDemoModuleChanged));
			DemoFlowDirectionProperty = DependencyProperty.Register("DemoFlowDirection", typeof(FlowDirection), ownerType, new PropertyMetadata(FlowDirection.LeftToRight, RaiseDemoFlowDirectionChanged));
			OwnerProperty = DependencyProperty.Register("Owner", typeof(object), ownerType, new PropertyMetadata(null, RaiseOwnerChanged));
			SidebarVisibilityProperty = DependencyProperty.Register("SidebarVisibility", typeof(Visibility), ownerType, new PropertyMetadata(Visibility.Collapsed, RaiseSidebarVisibilityChanged));
			SidebarTagProperty = DependencyProperty.Register("SidebarTag", typeof(string), ownerType, new PropertyMetadata("Sidebar", RaiseSidebarTagChanged));
			SidebarIconProperty = DependencyProperty.Register("SidebarIcon", typeof(ImageSource), ownerType, new PropertyMetadata(null, RaiseSidebarIconChanged));
			SidebarIconSelectedProperty = DependencyProperty.Register("SidebarIconSelected", typeof(ImageSource), ownerType, new PropertyMetadata(null, RaiseSidebarIconSelectedChanged));
		}
		int descriptionRowsCountValue = 1;
		List<object> linksValue = null;
		string optionsTopTextValue = string.Empty;
		bool isPopupContentInvisibleValue = true;
		bool isRTLSupportedValue = false;
		DemoModuleControlView demoModuleViewValue = DemoModuleControlView.Demo;
		DemoModuleControlOptionsView demoModuleOptionsViewValue = DemoModuleControlOptionsView.Options;
		FrameworkElement demoModuleValue = null;
		FlowDirection demoFlowDirectionValue = FlowDirection.LeftToRight;
		bool optionsExpandedValue = true;
		object ownerValue;
		Visibility sidebarVisibility = Visibility.Collapsed;
		string sidebarTag;
		ImageSource sidebarIcon;
		ImageSource sidebarIconSelected;
		static void RaiseSidebarVisibilityChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			((ModuleHelper)d).sidebarVisibility = (Visibility)e.NewValue;
		}
		static void RaiseSidebarTagChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			((ModuleHelper)d).sidebarTag = (string)e.NewValue;
		}
		static void RaiseSidebarIconChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			((ModuleHelper)d).sidebarIcon = (ImageSource)e.NewValue;
		}
		static void RaiseSidebarIconSelectedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			((ModuleHelper)d).sidebarIconSelected = (ImageSource)e.NewValue;
		}
		static void RaiseDescriptionRowsCountChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			((ModuleHelper)d).descriptionRowsCountValue = (int)e.NewValue;
		}
		static void RaiseLinksChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			((ModuleHelper)d).linksValue = (List<object>)e.NewValue;
		}
		static void RaiseOptionsTopTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			((ModuleHelper)d).optionsTopTextValue = (string)e.NewValue;
		}
		static void RaiseIsRTLSupportedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			((ModuleHelper)d).isRTLSupportedValue = (bool)e.NewValue;
		}
		static void RaiseDemoModuleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			((ModuleHelper)d).demoModuleValue = (FrameworkElement)e.NewValue;
		}
		static void RaiseOwnerChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			((ModuleHelper)d).ownerValue = e.NewValue;
		}
		static void RaiseDemoModuleViewChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			((ModuleHelper)d).demoModuleViewValue = (DemoModuleControlView)e.NewValue;
			((ModuleHelper)d).RaiseDemoModuleViewChanged(e);
		}
		static void RaiseDemoModuleOptionsViewChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			((ModuleHelper)d).demoModuleOptionsViewValue = (DemoModuleControlOptionsView)e.NewValue;
			((ModuleHelper)d).RaiseDemoModuleOptionsViewChanged(e);
		}
		static void RaiseIsPopupContentInvisibleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			((ModuleHelper)d).isPopupContentInvisibleValue = (bool)e.NewValue;
			((ModuleHelper)d).RaiseIsPopupContentInvisibleChanged(e);
		}
		static void RaiseDemoFlowDirectionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			((ModuleHelper)d).demoFlowDirectionValue = (FlowDirection)e.NewValue;
			((ModuleHelper)d).RaiseDemoFlowDirectionChanged(e);
		}
		static void RaiseOptionsExpandedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			((ModuleHelper)d).optionsExpandedValue = (bool)e.NewValue;
			((ModuleHelper)d).RaiseOptionsExpandedChanged(e);
		}
		#endregion
		Style demoModuleControlStyle;
		Action<ModuleHelper> endAppearAction;
		bool isPopupContentInvisibleInternal = true;
		public ModuleHelper(ContentPresenter demoModulePresenter, Style demoModuleControlStyle) {
			this.demoModuleControlStyle = demoModuleControlStyle;
			DemoModulePresenter = demoModulePresenter;
			DemoModulePresenter.SetBinding(ContentPresenter.ContentProperty, new Binding("DemoModule") { Source = this, Mode = BindingMode.OneWay });
		}
		public List<object> Links { get { return linksValue; } set { SetValue(LinksProperty, value); } }
		public int DescriptionRowsCount { get { return descriptionRowsCountValue; } private set { SetValue(DescriptionRowsCountProperty, value); } }
		public string OptionsTopText { get { return optionsTopTextValue; } private set { SetValue(OptionsTopTextProperty, value); } }
		public bool IsPopupContentInvisible { get { return isPopupContentInvisibleValue; } set { SetValue(IsPopupContentInvisibleProperty, value); } }
		public bool IsRTLSupported { get { return isRTLSupportedValue; } set { SetValue(IsRTLSupportedProperty, value); } }
		public DemoModuleControlView DemoModuleView { get { return demoModuleViewValue; } set { SetValue(DemoModuleViewProperty, value); } }
		public DemoModuleControlOptionsView DemoModuleOptionsView { get { return demoModuleOptionsViewValue; } set { SetValue(DemoModuleOptionsViewProperty, value); } }
		public bool OptionsExpanded { get { return optionsExpandedValue; } set { SetValue(OptionsExpandedProperty, value); } }
		public FlowDirection DemoFlowDirection { get { return demoFlowDirectionValue; } set { SetValue(DemoFlowDirectionProperty, value); } }
		public object Owner { get { return ownerValue; } set { SetValue(OwnerProperty, value); } }
		public ContentPresenter DemoModulePresenter { get; private set; }
		public FrameworkElement DemoModule { get { return demoModuleValue; } private set { SetValue(DemoModuleProperty, value); } }
		public Exception DemoModuleException { get; private set; }
		public CodeViewControl XamlTextViewer { get; private set; }
		public CodeViewControl CSCodeTextViewer { get; private set; }
		public CodeViewControl VBCodeTextViewer { get; private set; }
		public FrameworkElement DemoContentElement { get; private set; }
		public bool HasOptionsContent { get; private set; }
		public bool AllowThemeChange { get; private set; }
		public Visibility SidebarVisibility { get { return sidebarVisibility; } private set { SetValue(SidebarVisibilityProperty, value); } }
		public string SidebarTag { get { return sidebarTag; } private set { SetValue(SidebarTagProperty, value); } }
		public ImageSource SidebarIcon { get { return sidebarIcon; } private set { SetValue(SidebarIconProperty, value); } }
		public ImageSource SidebarIconSelected { get { return sidebarIconSelected; } private set { SetValue(SidebarIconSelectedProperty, value); } }
		public DemoModuleControlOptionsView? InitialOptionsView { get; set; }
		public bool CanLeave() {
			UCModule demoModule = DemoModule as UCModule;
			return demoModule == null || demoModule.CanLeave();
		}
		public void BeginAppearDemoModule(Type demoModuleType, Action<ModuleHelper> endAppearAction) {
			BackgroundHelper.DoInBackground(null, () => BeginAppearDemoModuleCore(demoModuleType, endAppearAction));
		}
        public void OpenModule(UCModule module,Action<ModuleHelper> endAppearAction)
        {
            if (module == null)
            {
                DemoModule = null;
                endAppearAction(this);
                return;
            }
            try
            {

                if (module.Content as DemoModuleControl == null)
                    module.Content = new DemoModuleControl();
                if (this.demoModuleControlStyle != null)
                    module.DemoModuleControl.Style = this.demoModuleControlStyle;
                module.BeginAppear();
                this.endAppearAction = endAppearAction;
                module.ActualLoaded += OnDemoModuleActualLoaded;
                module.IsPopupContentInvisible = true;
                DescriptionRowsCount = module.GetDescriptionRowsCount();
                SidebarVisibility = module.SupportSidebarContent() ? Visibility.Visible : Visibility.Collapsed;
                SidebarTag = module.GetSidebarTag();
                SidebarIcon = module.GetSidebarIcon();
                SidebarIconSelected = module.GetSidebarIconSelected();
                OptionsTopText = module.DemoModuleControl.OptionsTopText;
                AllowThemeChange = module.AllowSwitchingTheme;
                HasOptionsContent = module.DemoModuleControl.OptionsContent != null;
                module.SetBinding(UColor.WPF.UCModule.OwnerProperty, new Binding("Owner") { Source = this, Mode = BindingMode.OneWay });
                DemoModule = module;
            }
            catch (Exception e)
            {
                DemoModuleException = e;
                DemoModule = new TextBlock() { Foreground = new SolidColorBrush(Colors.Purple), TextWrapping = TextWrapping.Wrap, Text = ExceptionHelper.GetMessage(e) };
                endAppearAction(this);
            }
            InitDemoModuleOptionsView();
        }
		void BeginAppearDemoModuleCore(Type demoModuleType, Action<ModuleHelper> endAppearAction) {
			if(demoModuleType == null) {
				DemoModule = null;
				endAppearAction(this);
				return;
			}
			try {
				UCModule demoModule = CreateDemoModule(demoModuleType);
				if(demoModule.Content as DemoModuleControl == null)
					demoModule.Content = new DemoModuleControl();
				if(this.demoModuleControlStyle != null)
					demoModule.DemoModuleControl.Style = this.demoModuleControlStyle;
				demoModule.BeginAppear();
				this.endAppearAction = endAppearAction;
				demoModule.ActualLoaded += OnDemoModuleActualLoaded;
				demoModule.IsPopupContentInvisible = true;
				DescriptionRowsCount = demoModule.GetDescriptionRowsCount();
				SidebarVisibility = demoModule.SupportSidebarContent() ? Visibility.Visible : Visibility.Collapsed;
				SidebarTag = demoModule.GetSidebarTag();
				SidebarIcon = demoModule.GetSidebarIcon();
				SidebarIconSelected = demoModule.GetSidebarIconSelected();
				OptionsTopText = demoModule.DemoModuleControl.OptionsTopText;
				AllowThemeChange = demoModule.AllowSwitchingTheme;
				HasOptionsContent = demoModule.DemoModuleControl.OptionsContent != null;
				demoModule.SetBinding(UColor.WPF.UCModule.OwnerProperty, new Binding("Owner") { Source = this, Mode = BindingMode.OneWay });
				DemoModule = demoModule;
			} catch(Exception e) {
				DemoModuleException = e;
				DemoModule = new TextBlock() { Foreground = new SolidColorBrush(Colors.Purple), TextWrapping = TextWrapping.Wrap, Text = ExceptionHelper.GetMessage(e) };
				endAppearAction(this);
			}
			InitDemoModuleOptionsView();
		}
		public void EndAppearDemoModule() {
			UCModule demoModule = DemoModule as UCModule;
			if(demoModule != null)
				demoModule.EndAppear();
			isPopupContentInvisibleInternal = false;
			UpdateIsPopupContentInvisibleAndView();
		}
		public void BeginDisappearDemoModule(Action<ModuleHelper> endDisappearAction) {
			BackgroundHelper.DoInBackground(null, () => BeginDisappearDemoModuleCore(endDisappearAction));
		}
		void BeginDisappearDemoModuleCore(Action<ModuleHelper> endDisappearAction) {
			UCModule demoModule = DemoModule as UCModule;
			if(demoModule != null) {
				if(!demoModule.BeginDisappear()) return;
			}
			isPopupContentInvisibleInternal = true;
			UpdateIsPopupContentInvisibleAndView();
			endDisappearAction(this);
		}
		public void EndDispappearDemoModule() {
			UCModule demoModule = DemoModule as UCModule;
			DemoContentElement = null;
			CSCodeTextViewer = null;
			VBCodeTextViewer = null;
			XamlTextViewer = null;
			DemoModule = null;
			if(demoModule != null) {
				demoModule.Owner = null;
				demoModule.EndDisappear();
			}
			DescriptionRowsCount = 1;
			OptionsTopText = string.Empty;
			DemoModuleView = DemoModuleControlView.Demo;
			DemoModuleException = null;
			isPopupContentInvisibleInternal = true;
			UpdateIsPopupContentInvisibleAndView();
		}
		void OnDemoModuleActualLoaded(object sender, EventArgs e) {
			UCModule demoModule = (UCModule)sender;
			demoModule.ActualLoaded -= OnDemoModuleActualLoaded;
			CSCodeTextViewer = demoModule.DemoModuleControl.CSCodeTextViewer;
			VBCodeTextViewer = demoModule.DemoModuleControl.VBCodeTextViewer;
			XamlTextViewer = demoModule.DemoModuleControl.XamlTextViewer;
			DemoContentElement = demoModule.DemoModuleControl.DemoContentElement;
			UpdateDemoFlowDirection();
			if(endAppearAction != null) {
				this.endAppearAction(this);
				this.endAppearAction = null;
			}
		}
		void UpdateDemoFlowDirection() {
			UCModule demoModule = DemoModule as UCModule;
			if(demoModule == null) return;
#if SL
			demoModule.DemoModuleControl.OptionsContentContainer.FlowDirection = FlowDirection.LeftToRight;
#else
			foreach(FrameworkElement child in GetAllChildren(demoModule.DemoModuleControl, demoModule.DemoModuleControl.OptionsContentContainer)) {
				if(child != null)
					child.FlowDirection = FlowDirection.LeftToRight;
			}
#endif
			FlowDirectionHelper.SetFlowDirection(demoModule.DemoModuleControl, demoModule.AllowRtl ? DemoFlowDirection : FlowDirection.LeftToRight);
		}
		void RaiseDemoModuleOptionsViewChanged(DependencyPropertyChangedEventArgs e) {
			UpdateDemoModuleOptionsView();
		}
		void RaiseOptionsExpandedChanged(DependencyPropertyChangedEventArgs e) {
			UCModule demoModule = DemoModule as UCModule;
			if(demoModule == null) return;
			demoModule.DemoModuleControl.OptionsExpanded = OptionsExpanded;
		}
		void RaiseIsPopupContentInvisibleChanged(DependencyPropertyChangedEventArgs e) {
			UpdateIsPopupContentInvisibleAndView();
		}
		void RaiseDemoModuleViewChanged(DependencyPropertyChangedEventArgs e) {
			UpdateIsPopupContentInvisibleAndView();
		}
		void UpdateIsPopupContentInvisibleAndView() {
			UCModule demoModule = DemoModule as UCModule;
			if(demoModule == null) return;
			demoModule.IsPopupContentInvisible = isPopupContentInvisibleInternal || IsPopupContentInvisible || DemoModuleView != DemoModuleControlView.Demo;
			demoModule.DemoModuleControl.View = DemoModuleView;
		}
		void InitDemoModuleOptionsView() {
			UCModule demoModule = DemoModule as UCModule;
			if(demoModule == null) return;
			if(InitialOptionsView != null)
				demoModule.DemoModuleControl.OptionsView = (DemoModuleControlOptionsView)InitialOptionsView;
			DemoModuleOptionsView = demoModule.DemoModuleControl.OptionsView;
			bool optionsExpanded = DemoModuleOptionsView == DemoModuleControlOptionsView.Options ? demoModule.DemoModuleControl.OptionsExpanded : true;
			if(DemoModuleOptionsView == DemoModuleControlOptionsView.Sidebar && !demoModule.SupportSidebarContent())
				optionsExpanded = false;
			if(DemoModuleOptionsView == DemoModuleControlOptionsView.Options && demoModule.DemoModuleControl.OptionsContent == null)
				optionsExpanded = false;
			if(DemoModuleOptionsView == DemoModuleControlOptionsView.Themes && !demoModule.AllowSwitchingTheme)
				optionsExpanded = false;
			demoModule.DemoModuleControl.OptionsExpanded = optionsExpanded;
			OptionsExpanded = optionsExpanded;
		}
		void UpdateDemoModuleOptionsView() {
			UCModule demoModule = DemoModule as UCModule;
			if(demoModule == null) return;
			demoModule.DemoModuleControl.OptionsView = DemoModuleOptionsView;
		}
		void RaiseDemoFlowDirectionChanged(DependencyPropertyChangedEventArgs e) {
			FlowDirection newValue = (FlowDirection)e.NewValue;
			UpdateDemoFlowDirection();
		}
#if !SL
		IEnumerable<FrameworkElement> FindLogicalChildren(FrameworkElement root, Func<FrameworkElement, bool> condition) {
			foreach(FrameworkElement child in LogicalTreeHelper.GetChildren(root)) {
				if(condition(child))
					yield return child;
			}
		}
		bool IsVisualParent(FrameworkElement child, FrameworkElement parent, FrameworkElement root) {
			for(FrameworkElement node = child; node != null && node != root; ) {
				FrameworkElement nodeParent = VisualTreeHelper.GetParent(node) as FrameworkElement;
				if(nodeParent == parent) return true;
				node = nodeParent;
			}
			return false;
		}
		IEnumerable<FrameworkElement> GetAllChildren(FrameworkElement root, FrameworkElement visualParent) {
			foreach(FrameworkElement child in FindLogicalChildren(root, fe => IsVisualParent(fe, visualParent, root))) {
				yield return child;
			}
			yield return visualParent;
		}
#endif
		void ApplyToAllChildren(FrameworkElement root, Action<FrameworkElement> action, int depth) {
			if(depth < 0) return;
			action(root);
			if(depth < 1) return;
			for(int i = VisualTreeHelper.GetChildrenCount(root); --i >= 0; ) {
				FrameworkElement child = VisualTreeHelper.GetChild(root, i) as FrameworkElement;
				if(child != null)
					ApplyToAllChildren(child, action, depth - 1);
			}
		}
		UCModule CreateDemoModule(Type demoModuleType) {
			UCModule demoModule = (UCModule)Activator.CreateInstance(demoModuleType);
			demoModule.Width = demoModule.Height = double.NaN;
			demoModule.MaxWidth = demoModule.MaxHeight = double.PositiveInfinity;
			return demoModule;
		}
	}
}
